#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/kthread.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/types.h>
#include <linux/string.h>
#include <asm/byteorder.h>
#include <linux/log2.h>
#include <linux/byteorder/generic.h>
#include <linux/kernel.h>
#include <linux/compiler.h>
#include <crypto/hash.h>
#include <linux/crypto.h>
#include <linux/hashtable.h>
#include "mctp.h"

#define DEVICE_NAME             "mctp"
#define CLASS_NAME              "mctp"

static struct class *mctp;
static dev_t devt;
static struct cdev mctp_cdev;
static struct str_queue global_queue;
static struct mctp_cache buffer_cache __read_mostly;
static MCTP_ncsi_key global_mctp_read;
// 定义工作队列和延迟工作结构
static struct workqueue_struct *cache_cleanup_wq;
static struct delayed_work cache_cleanup_work;

static int str_node_count = 0;
static int write_count = 0;
static int package_number = 0;

static DEFINE_MUTEX(md5_mutex);
static DEFINE_MUTEX(kv_lock);

u8 stored_md5[16] = {};


#define BYTES_PER_LINE 16
/* 内核日志打印函数, 便于调试 */
void log_buffer_content(const char *buffer, size_t len, const char *tag)
{
    unsigned long i;
    char hex_line[BYTES_PER_LINE * 3 + 1] = {0};
    char ascii_line[BYTES_PER_LINE + 1] = {0};

    if (len == 0) {
        pr_err("%s: [EMPTY BUFFER]", tag);
        return;
    }

    for (i = 0; i < len; i++) {
        unsigned long pos = i % BYTES_PER_LINE;
        unsigned char ch = (unsigned char)buffer[i];

        /* 安全构建十六进制行 */
        scnprintf(hex_line + pos * 3, 4, "%02X ", ch);

        /* 构建ASCII行*/
        ascii_line[pos] = (ch >= 32 && ch <= 126) ? ch : '.';

        if (pos == BYTES_PER_LINE - 1 || i == len - 1) {
            ascii_line[pos + 1] = '\0';

            printk("%s [%04lX] %-48s | %s\n",
                tag,
                (i - pos) & 0xFFFF,
                hex_line,
                ascii_line);
            
            /* 安全重置缓冲区 */
            memset(hex_line, 0, sizeof(hex_line));
            memset(ascii_line, 0, sizeof(ascii_line));
        }
    }
}

/* 查找函数 */
ssize_t lookup_fixed_table(const char *key, const size_t len)
{
    int i = 0;
    for (i = 0; i < ARRAY_SIZE(fixed_table); i++)
    {
        // 前缀匹配
        if (strncmp(fixed_table[i].key, key, len) == 0) {
            return fixed_table[i].value;
        }
    }
    pr_debug("mctp key not found: %s\n", key);
    return 0xF;
}

/* 初始化队列 */
static void init_queue(struct str_queue *q)
{
    mutex_init(&q->lock);
    q->head = q->tail = NULL;
}

/* 入队操作 */
static int enqueue(struct str_queue *q, const char *str)
{
    int ret = 0;
    struct str_node *new_node = kmalloc(sizeof(*new_node), GFP_KERNEL);
    if (!new_node) {
        pr_err("kmalloc failed\n");
        return -ENOMEM;
    }

    new_node->data = kstrdup(str, GFP_KERNEL);
    if (!new_node->data) {
        pr_err("data failed\n");
        kfree(new_node);
        return -ENOMEM;
    }
    new_node->next = NULL;

    mutex_lock(&q->lock);
    if (!q->head) {
        q->head = q->tail = new_node;
    } else {
        q->tail->next = new_node;
        q->tail = new_node;
    }
    mutex_unlock(&q->lock);
    return ret;
}

/* 出队操作 */
static char *dequeue(struct str_queue *q)
{
    struct str_node *temp;
    char *ret = NULL;

    mutex_lock(&q->lock);
    if (q->head) {
        temp = q->head;
        ret = temp->data;
        q->head = q->head->next;
        if (!q->head) {
            q->tail = NULL;
        }
        kfree(temp);
    }
    mutex_unlock(&q->lock);
    return ret;
}

/* 队列清除函数 */
static void destroy_queue(struct str_queue *q)
{
    struct str_node *cur, *next;
    mutex_lock(&q->lock);
    cur = q->head;
    while (cur) {
        next = cur->next;
        kfree(cur->data);
        kfree(cur);
        cur = next;
    }
    q->head = q->tail = NULL;
    mutex_unlock(&q->lock);
}

/* 读取文件内容 */
static int read_file(const char *path, char **buffer, size_t *size)
{
    struct file *file;
    loff_t pos = 0;
    int ret;

    file = filp_open(path, O_RDONLY, 0);
    if (IS_ERR(file)) {
        pr_err("Failed to open file: %s\n", path);
        return PTR_ERR(file);
    }

    *size = i_size_read(file->f_inode);
    *buffer = kmalloc(*size, GFP_KERNEL);
    if (!*buffer) {
        filp_close(file, NULL);
        return -ENOMEM;
    }

    ret = kernel_read(file, *buffer, *size, &pos);
    if (ret < 0) {
        pr_err("Failed to read file: %s\n", path);
        kfree(*buffer);
        filp_close(file, NULL);
        return ret;
    }

    filp_close(file, NULL);
    return 0;
}

/* 计算MD5哈希 */
static int calculate_md5(const char *data, size_t size, u8 *md5)
{
    struct crypto_shash *tfm;
    struct shash_desc *desc;
    int ret;

    tfm = crypto_alloc_shash("md5", 0, 0);
    if (IS_ERR(tfm)) {
        pr_err("Failed to allocate MD5 transform.\n");
        return PTR_ERR(tfm);
    }

    desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
    if (!desc) {
        crypto_free_shash(tfm);
        return -ENOMEM;
    }

    desc->tfm = tfm;

    ret = crypto_shash_init(desc);
    if (ret) {
        pr_err("Failed to initialize MD5 transform.\n");
        goto error;
    }

    ret = crypto_shash_update(desc, data, size);
    if (ret) {
        pr_err("Failed to update MD5 transform.\n");
        goto error;
    }

    ret = crypto_shash_final(desc, md5);
    if (ret) {
        pr_err("Failed to finalize MD5 transform.\n");
        goto error;
    }

error:
    kfree(desc);
    crypto_free_shash(tfm);
    return ret;
}

/* MD5比较函数 */
static int compare_md5(const u8 *a, const u8 *b)
{
    return memcmp(a, b, sizeof(stored_md5));
}

// 添加文件存在性检查函数
static int file_exists(const char *path)
{
    struct file *file;
    
    file = filp_open(path, O_RDONLY, 0);
    if (IS_ERR(file)) {
        pr_debug("File %s does not exist: error %ld\n", path, PTR_ERR(file));
        return 0; // 文件不存在
    }
    
    filp_close(file, NULL);
    pr_debug("File %s exists\n", path);
    return 1; // 文件存在
}


/* 根据比较MD5来判断文件是否变化 */
static int bdf_change(void)
{
    char *buffer = NULL;
    size_t size;
    u8 md5[16];
    int ret;
    int changed = 0;        // 记录是否变化

    // 先检查文件是否存在
    if (!file_exists(FILE_PATH)) {
        pr_debug("File %s does not exist, skipping MD5 check.\n", FILE_PATH);
        return -ENOENT; // 返回文件不存在的错误码
    }

    ret = read_file(FILE_PATH, &buffer, &size);
    if (ret) {
        pr_err("File read error.\n");
        return ret;
    }

    ret = calculate_md5(buffer, size, md5);
    if (ret) {
        pr_err("MD5 calculation error.\n");
        goto cleanup;
    }

    // 加锁比较和更新
    mutex_lock(&md5_mutex);
    if (compare_md5(md5, stored_md5) != 0) {
        memcpy(stored_md5, md5, sizeof(stored_md5));
        pr_info("File has changed.\n");
        changed = 1;
    }
    mutex_unlock(&md5_mutex);

cleanup:
    if (buffer) {
        kfree(buffer);
    }

    // 返回是否变化 (0=未变, 1=变化)
    return changed;
}

/* 初始化MD5 */
static int calculate_init_md5(void)
{
    char *buffer = NULL;
    size_t size;
    int ret;
    
    ret = read_file(FILE_PATH, &buffer, &size);
    if (ret) {
        pr_err("mctp read bdf file failed.\n");
        goto out;
    }

    // 加锁更新全局MD5
    mutex_lock(&md5_mutex);
    ret = calculate_md5(buffer, size, stored_md5);
    mutex_unlock(&md5_mutex);

    if (ret) {
        pr_err("mctp calculate init md5 failed.\n");
    } else {
        pr_debug("mctp calculate init md5 success.\n");
    }

out:
    if (buffer) {
        kfree(buffer);
    }
    return ret;
}

// 计算文件路径的哈希值
static unsigned int file_path_hash(const char *path)
{
    return full_name_hash(NULL, path, strlen(path));
}

// 根据路径查找缓存条目
struct file_cache_entry *find_cache_entry(const char *path)
{
    struct file_cache_entry *entry;
    unsigned int hash = file_path_hash(path);

    mutex_lock(&cache_table_mutex);
    hash_for_each_possible(file_cache_table, entry, hash_node, hash) {
        if (strcmp(entry->path, path) == 0) {
            mutex_unlock(&cache_table_mutex);
            return entry;
        }
    }
    mutex_unlock(&cache_table_mutex);
    return NULL;
}

// 创建新的缓存条目
struct file_cache_entry *create_cache_entry(const char *path)
{
    struct file_cache_entry *entry;
    struct file *file;
    loff_t pos = 0;
    int ret;
    
    // 分配缓存条目
    entry = kmalloc(sizeof(struct file_cache_entry), GFP_KERNEL);
    if (!entry) {
        pr_err("Failed to allocate cache entry.\n");
        return ERR_PTR(-ENOMEM);
    }
    
    // 保存文件路径
    entry->path = kstrdup(path, GFP_KERNEL);
    if (!entry->path) {
        pr_err("Failed to duplicate path.\n");
        kfree(entry);
        return ERR_PTR(-ENOMEM);
    }
    
    // 打开文件
    file = filp_open(path, O_RDONLY, 0);
    if (IS_ERR(file)) {
        ret = PTR_ERR(file);
        pr_err("Failed to open file: %s, error: %d.\n", path, ret);
        kfree(entry->path);
        kfree(entry);
        return ERR_PTR(ret);
    }
    
    // 获取文件大小
    entry->cache_size = i_size_read(file->f_inode);
    if (entry->cache_size == 0) {
        pr_err("File is empty: %s.\n", path);
        filp_close(file, NULL);
        kfree(entry->path);
        kfree(entry);
        return ERR_PTR(-EINVAL);
    }
    
    // 分配缓存空间
    entry->cache_data = kmalloc(entry->cache_size, GFP_KERNEL);
    if (!entry->cache_data) {
        pr_err("Failed to allocate cache buffer for %s.\n", path);
        filp_close(file, NULL);
        kfree(entry->path);
        kfree(entry);
        return ERR_PTR(-ENOMEM);
    }
    
    // 读取文件到缓存
    ret = kernel_read(file, entry->cache_data, entry->cache_size, &pos);
    filp_close(file, NULL);
    
    if (ret < 0) {
        pr_err("Failed to read file %s, error: %d.\n", path, ret);
        kfree(entry->cache_data);
        kfree(entry->path);
        kfree(entry);
        return ERR_PTR(ret);
    }
    
    if (ret < entry->cache_size) {
        pr_debug("Partial read for %s: got %d bytes, expected %zu bytes.\n", 
                 path, ret, entry->cache_size);
        entry->cache_size = ret;
    }

    // 记录创建时间
    entry->create_time = jiffies;
    
    // 添加到哈希表
    mutex_lock(&cache_table_mutex);
    hash_add(file_cache_table, &entry->hash_node, file_path_hash(path));
    mutex_unlock(&cache_table_mutex);
    
    pr_debug("File cache created for %s. Size: %zu bytes.\n", path, entry->cache_size);
    return entry;
}

// 从缓存读取数据到内核缓冲区
int read_from_cache(const char *path, u32 offset, char *kernel_buf, size_t buf_size)
{
    struct file_cache_entry *entry;
    size_t read_size;
    
    // 获取或创建缓存条目
    entry = find_cache_entry(path);

    /* 如果找到条目但文件已不存在, 则删除缓存条目 */
    if (entry && !file_exists(path)) {
        mutex_lock(&cache_table_mutex);
        hash_del(&entry->hash_node);
        kfree(entry->cache_data);
        kfree(entry->path);
        kfree(entry);
        mutex_unlock(&cache_table_mutex);
        entry = NULL;
    }

    /* 获取或创建缓存条目 */
    if (!entry) {
        // 如果文件不存在，直接返回报错
        if (!file_exists(path)) {
            pr_err("File %s does not exist, cannot create cache entry.\n", path);
            return -ENOMEM;
        }

        pr_debug("mctp no find cache entry!");
        entry = create_cache_entry(path);
        if (IS_ERR(entry)) {
            return PTR_ERR(entry);
        }
    }
    
    // 检查偏移量是否有效
    if (offset >= entry->cache_size) {
        pr_debug("Offset %u exceeds file size %zu for %s.\n", 
               offset, entry->cache_size, path);
        return -EINVAL;
    }
    
    // 计算实际要读取的大小
    read_size = min_t(size_t, buf_size, entry->cache_size - offset);
    
    // 从缓存复制数据
    memcpy(kernel_buf, entry->cache_data + offset, read_size);
    
    // 如果数据不足，用0填充
    if (read_size < buf_size) {
        memset(kernel_buf + read_size, 0, buf_size - read_size);
        pr_debug("Partial read from cache for %s, padded with zeros.\n", path);
    }
    
    return buf_size;
}

// 清理所有缓存
void cleanup_all_file_cache(void)
{
    struct file_cache_entry *entry;
    struct hlist_node *tmp;
    int bkt;
    
    mutex_lock(&cache_table_mutex);
    hash_for_each_safe(file_cache_table, bkt, tmp, entry, hash_node) {
        hash_del(&entry->hash_node);
        kfree(entry->cache_data);
        kfree(entry->path);
        kfree(entry);
    }
    mutex_unlock(&cache_table_mutex);
    pr_debug("All file caches cleaned up.\n");
}

/* 工作队列处理函数 */
static void cache_cleanup_work_fn(struct work_struct *work)
{
    struct file_cache_entry *entry;
    struct hlist_node *tmp;
    int bkt;
    unsigned long now = jiffies;
    unsigned long expire_time = 15 * HZ; // 15秒
    bool need_remove = false;
    char *remove_reason = NULL;
    
    mutex_lock(&cache_table_mutex);
    
    hash_for_each_safe(file_cache_table, bkt, tmp, entry, hash_node) {
        need_remove = false;
        remove_reason = NULL;

        /* 检查文件是否存在，如果不存在则立即删除缓存 */
        if (!file_exists(entry->path)) {
            remove_reason = "File no longer exists";
            need_remove = true;
        } 
        /* 检查是否超过15s的生命周期 */
        else if (time_after(now, entry->create_time + expire_time)) {
            remove_reason = "Expired";
            need_remove = true;
        }

        if (need_remove) {
            pr_debug("%s: %s, removing cache entry: %s\n",entry->path, remove_reason, entry->path);
            hash_del(&entry->hash_node);
            kfree(entry->cache_data);
            kfree(entry->path);
            kfree(entry);
        }
        
    }
    
    mutex_unlock(&cache_table_mutex);
    
    // 重新调度工作（每5秒检查一次）
    queue_delayed_work(cache_cleanup_wq, &cache_cleanup_work, 5 * HZ);
}

/* 根据变化的bdf来更新routing table */
static char* modify_routing_buffer(char* kernel_buf, size_t n_bdf_entries, char* bdf_buf)
{
    /* 根据变化的routing的来计算responce的长度
       因为length_value都是4的倍数，所以需要向上取整 */
    int length_value = (ROUTING_HEAD_LEN + ROUTING_LEN * (n_bdf_entries + 1)) / 4 + 1;
    // EID：os是08， BMC是11， 其他pcie卡从9开始计算
    u8 id_counter = 9;
    int i;

    // 检查取值范围
    if (length_value < 0 || length_value > 255) {
        pr_err("Invalid length value: %d.\n", length_value);
        return NULL;
    }

    // 首字节是response的长度
    kernel_buf[0] = (u8)length_value;

    // 调试输出
    pr_info("Set length field: dec=%d -> hex=0x%02X\n", length_value, kernel_buf[0]);

    /* 设置路由表头部信息 */
    kernel_buf[21] = n_bdf_entries + 1;     // pcie卡的条目数 + BMC条目数
    kernel_buf[22] = 0x01;
    kernel_buf[23] = 0x0B;
    kernel_buf[24] = 0x20;
    kernel_buf[25] = 0x02;
    kernel_buf[26] = 0x0F;
    kernel_buf[27] = 0x02;
    kernel_buf[28] = 0x03;
    kernel_buf[29] = 0x00;

    /* 填充pcie卡的条目, 从offset = 30开始 */
    int current_offset = 30;
    for (i = 0; i < n_bdf_entries; i++) {
        int bdf_num = i*3;        // bdf是3个为一体
        u8 bus = bdf_buf[bdf_num];
        u8 device = bdf_buf[bdf_num + 1];
        u8 function = bdf_buf[bdf_num + 2];

        /*检查ID有效性，需要跳过BMC的11*/
        if (id_counter == 0x0B) {
            id_counter++;
        }

        if (id_counter > 0xFF) {
            pr_err("ID counter overflow.\n");
            return NULL;
        }

        /* 填充pcie卡的条目 */
        kernel_buf[current_offset] = 0x01;
        kernel_buf[current_offset + 1] = id_counter++;
        kernel_buf[current_offset + 2] = 0x20;
        kernel_buf[current_offset + 3] = 0x02;
        kernel_buf[current_offset + 4] = 0x0F;
        kernel_buf[current_offset + 5] = 0x02;
        kernel_buf[current_offset + 6] = bus;
        kernel_buf[current_offset + 7] = (device << 4) | (function & 0x0F);

        current_offset += ROUTING_LEN;
        if (current_offset + ROUTING_LEN > MCTP_MAX_PACKET_SIZE) {
            pr_err("Routing table overflow.\n");
            return NULL;
        }
    }

    return kernel_buf;
}

// 删除缓存条目
static void delete_cache_entry(const char *path)
{
    struct file_cache_entry *entry;
    unsigned int hash = file_path_hash(path);

    mutex_lock(&cache_table_mutex);
    hash_for_each_possible(file_cache_table, entry, hash_node, hash) {
        if (strcmp(entry->path, path) == 0) {
            // 从哈希表中移除
            hash_del(&entry->hash_node);
            
            // 释放内存
            kfree(entry->path);
            kfree(entry->cache_data);
            kfree(entry);
            
            pr_debug("Cache entry deleted for %s.\n", path);
            break;
        }
    }
    mutex_unlock(&cache_table_mutex);
}

/* 更改mctp返回的routing内容 */
static int change_routing_table(void)
{
    struct file *file;
    loff_t pos = 0x220;
    char *kernel_buf;
    int ret = 0;
    loff_t pos_bdf = 0x00;
    size_t n_bdf_entries;
    int i;
    size_t bdf_size = 0;
    char *bdf_buf = NULL;
    const char *path = "/mockdata/pciecard/0x00_0x0000_mctp.bin";

    kernel_buf = kmalloc(MCTP_MAX_PACKET_SIZE, GFP_KERNEL);
    if (!kernel_buf) {
        pr_err("Failed to allocate kernel buffer.\n");
        return -ENOMEM;
    }

    file = filp_open(path, O_RDWR, 0);
    if (IS_ERR(file)) {
        ret = PTR_ERR(file);
        pr_debug("Failed to open origin mctp file: %s, error: %d.\n", path, ret);
        kfree(kernel_buf);
        return ret;
    }

    ret = kernel_read(file, kernel_buf, MCTP_MAX_PACKET_SIZE, &pos);

    if (ret < 0) {
        pr_err("Failed to read file, error: %d.\n", ret);
        goto out_close;
    } else if (ret < MCTP_MAX_PACKET_SIZE) {
        memset(kernel_buf + ret, 0, MCTP_MAX_PACKET_SIZE - ret);
        pr_debug("Partial read, padded with zeros.\n");
    }

    int read_ret = read_file(FILE_PATH, &bdf_buf, &bdf_size);
    if (read_ret < 0) {
        ret = read_ret;
        pr_err("Failed to read BDF file: %d.\n", read_ret);
        goto out_close;
    }

    if (bdf_size % BDF_ENTRY_SIZE != 0) {
        pr_debug("BDF file size %zu not multiple of %d, truncating.\n",
                bdf_size, (bdf_size / BDF_ENTRY_SIZE) * BDF_ENTRY_SIZE);
        bdf_size = (bdf_size / BDF_ENTRY_SIZE) * BDF_ENTRY_SIZE;
    }

    n_bdf_entries = bdf_size / BDF_ENTRY_SIZE;
    pr_info("Found %zu BDF entries.\n", n_bdf_entries);

    kernel_buf = modify_routing_buffer(kernel_buf, n_bdf_entries, bdf_buf);
    if (!kernel_buf) {
        pr_err("Modify routing buffer failed.\n");
        goto out_close;
    }

    pos = 0x220;
    ret = kernel_write(file, kernel_buf, MCTP_MAX_PACKET_SIZE, &pos);
    if (ret < 0) {
        pr_err("Failed to write routing table: %d.\n", ret);
    } else {
        pr_info("Routing table updated with %d entries.\n", n_bdf_entries);

        // 删除缓存条目，强制下次读取时重新创建缓存
        delete_cache_entry(path);
        pr_info("Cache invalidated for %s, will be recreated on next read.\n", path);

        // 强制同步到磁盘, 第二个参数0表示同步到整个文件
        ret = vfs_fsync(file, 0);
        if (ret < 0) {
            pr_err("Failed to sync file: %d.\n", ret);
        }
    }

    pos = 0x220;
    char* modify_buf;
    modify_buf = kmalloc(MCTP_MAX_PACKET_SIZE, GFP_KERNEL);
    ret = kernel_read(file, modify_buf, MCTP_MAX_PACKET_SIZE, &pos);

out_close:
    filp_close(file, NULL);
    kfree(bdf_buf);
    kfree(kernel_buf);
    kfree(modify_buf);
    return ret;
}

static int hex_char_to_byte(char c)
{
    if (c >= '0' && c <= '9') return c - '0';
    if (c >= 'a' && c <= 'f') return c - 'a' + 10;
    if (c >= 'A' && c <= 'F') return c - 'A' + 10;
    return 0;
}

/* 读取control的文件 */
static int read_control_bin(u32 offset, char __user *buf, char* key)
{
    char *kernel_buf;
    int ret = 0;
    const char *path = "/mockdata/pciecard/0x00_0x0000_mctp.bin";

    kernel_buf = kmalloc(MCTP_MAX_PACKET_SIZE, GFP_KERNEL);
    if (!kernel_buf) {
        pr_err("Failed to allocate kernel buffer.\n");
        return -ENOMEM;
    }

    // 使用缓存读取数据
    ret = read_from_cache(path, offset, kernel_buf, MCTP_MAX_PACKET_SIZE);
    if (ret < 0) {
        kfree(kernel_buf);
        return ret;
    }

    if (strcmp(key, "00000000000000") != 0) {
        pr_debug("Processing non-default key: %s.\n", key);

        MCTP_control_key control_key;
        int i;
        for (i = 0; i < sizeof(control_key); i++) {
            char hex_byte[3] = { key[2*i], key[2*i+1], '\0' };
            unsigned int byte_val;
            if (kstrtouint(hex_byte, 16, &byte_val) || byte_val > 0xFF) {
                pr_err("Invalid hex byte: %s.\n", hex_byte);
                kfree(kernel_buf);
                return -EINVAL;
            }
            ((u8 *)&control_key)[i] = (u8)byte_val;
        }
        kernel_buf[12] |= control_key.msg_tag;
        kernel_buf[17] |= control_key.instance_id;
    }

    /* 复制用户空间 */
    if (copy_to_user(buf, kernel_buf, MCTP_MAX_PACKET_SIZE))
    {
        pr_err("Copy to user failed.\n");
        ret = -EFAULT;
    } else {
        ret = MCTP_MAX_PACKET_SIZE;
    }

    kfree(kernel_buf);
    return ret;
}

/* 长度解析函数 */
static inline u16 get_mctp_length(const mctp_header *hdr)
{
    u16 raw = le16_to_cpu(hdr->raw_len);

    return ((raw & 0x0300) >> 8) | ((raw & 0x00FF) << 2);
}

static int get_byte(int package_number, int msg_tag, int SOM, int EOM)
{
    /* 计算包序列号 (模4运算) */
    const int package_seq = (package_number - 1) % 4;

    /* 位域组装 */
    unsigned char byte = 0;

    /* 设置SOM位 */
    byte |= (SOM ? 1 : 0) << 7;

    /* 设置EOM位 */
    byte |= (EOM ? 1 : 0) << 6;

    /* 设置包序列号 */
    byte |= (package_seq & 0x03) << 4;

    /* 设置消息标签 */
    byte |= (msg_tag & 0x07);

    return (int)byte;
}

/* 校验和计算函数 */
int32_t twocpl_checks_sum(const char *data, size_t len)
{
    uint32_t sum = 0;
    size_t i = 0;

    while (i + 1 < len) {
        uint16_t word;
        __builtin_memcpy(&word, &data[i], sizeof(word));
        sum += ntohs(word);
        i += sizeof(uint16_t);
    }

    if (i < len) {
        sum += data[i];
    }

    sum = (~sum) + 1;
    return (int32_t)sum;
}

static void cache_write(const u8 *src, size_t len)
{
    mutex_lock(&buffer_cache.lock);

    if (unlikely(buffer_cache.total_len + len > MAX_CACHE_SIZE))
    {
        pr_err_ratelimited("MCTP cache overflow! %zu + %zu > %d.\n",
                            buffer_cache.total_len, len, MAX_CACHE_SIZE);
        goto unlock;
    }

    memcpy(buffer_cache.data + buffer_cache.total_len, src, len);
    buffer_cache.total_len += len;

unlock:
    mutex_unlock(&buffer_cache.lock);
}

static void cache_reset(void)
{
    mutex_lock(&buffer_cache.lock);
    buffer_cache.total_len = 0;
    buffer_cache.is_active = false;
    mutex_unlock(&buffer_cache.lock);
}

static char* modify_kernel_buf(char *kernel_buf, uint8_t som, uint8_t eom, 
                            u32 match_key, u16 length, MCTP_ncsi_key ncsi_key)
{
    const size_t data_offset = 16;
    const u8* payload = (const u8 *)kernel_buf + data_offset;
    size_t data_len = length;

    kernel_buf[13] = global_mctp_read.dest_eid;
    kernel_buf[7] = (uint8_t)(global_mctp_read.target_id >> 8);

    if (som) {
        cache_reset();

        kernel_buf[20] = ncsi_key.iid;

        switch (match_key) {
            case 0x50010400:
            case 0x50010000:
                kernel_buf[22] = ncsi_key.channel_id;
                kernel_buf[44] = ncsi_key.channel_id;
                kernel_buf[54] = (unsigned char)(kernel_buf[54] + ncsi_key.channel_id);
                break;
            case 0x00000000:
            case 0x50000e01:
            case 0x50010200:
            case 0x50000f00:
                kernel_buf[22] = ncsi_key.channel_id;
                break;
            case 0x50000100:
                kernel_buf[22] = ncsi_key.channel_id;
                kernel_buf[44] = ncsi_key.channel_id;
                kernel_buf[48] = ncsi_key.channel_id;
                break;
            case 0x0A000000:
                kernel_buf[22] = ncsi_key.channel_id;
                if (ncsi_key.channel_id) {
                    kernel_buf[40] = 0x14;
                }
                break;
            case 0x50000B00:
                kernel_buf[22] = ncsi_key.channel_id;
                if (ncsi_key.channel_id) {
                    kernel_buf[44] = ncsi_key.channel_id;
                    kernel_buf[45] = 0x7F;
                    kernel_buf[46] = 0xFE;
                }
                break;
            default:
                break;
        }

        payload += 1;
        length -= 1;
    }

    cache_write(payload, length);

    if (eom) {
        size_t checksum_len;
        int32_t checksum;
        union checksum_conv conv;
        package_number = 0;

        mutex_lock(&buffer_cache.lock);

        checksum_len = (buffer_cache.total_len > 7) ? (buffer_cache.total_len - 7) : 0;

        checksum = twocpl_checks_sum((u8 *)buffer_cache.data, checksum_len);
        conv.value = htonl((uint32_t)checksum);

        const size_t checksum_offset = data_offset + data_len - 7;

        memcpy(kernel_buf  +checksum_offset, conv.bytes, sizeof(conv.bytes));

        mutex_unlock(&buffer_cache.lock);
        cache_reset();
    }

    return kernel_buf;
}

static int process_key(const char *key)
{
    int num_valid_keys = sizeof(valid_keys) / sizeof(valid_keys[0]);

    /* 检查key是否在有效key列表 */
    int key_is_valid = 0;
    int i;
    for (i = 0; i < num_valid_keys; i++) {
        if (strcmp(key, valid_keys[i]) == 0)
        {
            key_is_valid = 1;
            break;
        }
    }

    if (!key_is_valid)
    {
        return 0;
    }

    return 0xFF;
}

static u32 form_match_key(char *key)
{
    if (!key)
    {
        return 0xF;
    }

    char hex_byte[3] = {0};
    unsigned int msg_type = 0;

    /* 提取前两个字符 */
    strncpy(hex_byte, key, 2);
    if (kstrtouint(hex_byte, 16, &msg_type) != 0)
    {
        pr_err("MCTP invalid msg_type format: %s", hex_byte);
        return -EINVAL;
    }

    if (msg_type && (process_key(key) == 0))
    {
        MCTP_ncsi_key ncsi_key;
        int i;
        
        for (i = 0; i < sizeof(ncsi_key); i++)
        {
            char hex_byte[3] = { key[2*i], key[2*i + 1], '\0' };
            unsigned int byte_val;
            if (kstrtouint(hex_byte, 16, &byte_val) || byte_val > 0xFF)
            {
                pr_err("Invalid hex byte: %s.\n", hex_byte);
                return -EINVAL;
            }
            ((u8 *)&ncsi_key)[i] = (u8)byte_val;
        }

        return ((u32)ncsi_key.command_type << 24) |
            ((u32)ncsi_key.hw_cmd << 16) |
            ((u32)ncsi_key.sub_cmd << 8) |
            (u32)ncsi_key.extra_cmd;
    }

    return 0xF;
}

static int read_ncsi_bin(u32 offset, char __user *buf, char *key)
{
    char *kernel_buf;
    int ret = 0;
    char path[256];
    MCTP_ncsi_key ncsi_key;

    if (process_key(key) == 0)
    {
        int i;
        for (i = 0; i < sizeof(ncsi_key); i++)
        {
            char hex_byte[3] = { key[2*i], key[2*i + 1], '\0' };
            unsigned int byte_val;
            if (kstrtouint(hex_byte, 16, &byte_val) || byte_val > 0xFF)
            {
                pr_err("Invalid hex byte: %s.\n", hex_byte);
                return -EINVAL;
            }
            ((u8 *)&ncsi_key)[i] = (u8)byte_val;
        }

        ncsi_key.requester_eid = (ncsi_key.requester_eid >> 8) | (ncsi_key.requester_eid << 8);
        ncsi_key.target_id = (ncsi_key.target_id >> 8) | (ncsi_key.target_id << 8);

        /* 考虑多包场景 */
        global_mctp_read.msg_tag = ncsi_key.msg_tag;
        global_mctp_read.target_id = ncsi_key.target_id;
        global_mctp_read.dest_eid = ncsi_key.dest_eid;
        global_mctp_read.msg_type = ncsi_key.msg_type;
    }

    // 生成路径
    int path_len = snprintf(path, sizeof(path),
        "/mockdata/pciecard/0x%02hhx_0x%04hx_mctp.bin",
        global_mctp_read.msg_type,
        global_mctp_read.target_id);
    
    // 检查路径长度是否有效
    if (path_len >= sizeof(path)) {
        pr_err("Generated path too long: %s\n", path);
        return -ENAMETOOLONG;
    }
    
    pr_debug("Generated path: %s\n", path);
    pr_debug("global_mctp_read.msg_type: 0x%08x, global_mctp_read.target_id: 0x%08x", 
             global_mctp_read.msg_type, global_mctp_read.target_id);
    
    // 检查文件是否存在
    if (!file_exists(path)) {
        pr_info("File %s does not exist, returning error.\n", path);
        return -ENOENT;
    }
    
    kernel_buf = kmalloc(MCTP_MAX_PACKET_SIZE, GFP_KERNEL);
    if (!kernel_buf)
    {
        pr_err("Failed to allocate kernel buffer.\n");
        return -ENOMEM;
    }

    // 使用缓存读取数据
    ret = read_from_cache(path, offset, kernel_buf, MCTP_MAX_PACKET_SIZE);
    if (ret < 0) {
        kfree(kernel_buf);
        return ret;
    }

    const mctp_header *hdr = (const mctp_header *)kernel_buf;
    u16 length = get_mctp_length(hdr);
    u8 som = hdr->SOM;
    u8 eom = hdr->EOM;

    mutex_lock(&kv_lock);
    package_number++;
    kernel_buf[12] = get_byte(package_number, global_mctp_read.msg_tag, som, eom);

    u32 match_key = form_match_key(key);
    kernel_buf = modify_kernel_buf(kernel_buf, som, eom, match_key, length, ncsi_key);
    mutex_unlock(&kv_lock);

    if (copy_to_user(buf, kernel_buf, MCTP_MAX_PACKET_SIZE))
    {
        ret = -EFAULT;
        pr_err("Copy to user failed.\n");
    } else {
        ret = MCTP_MAX_PACKET_SIZE;
    }

    kfree(kernel_buf);
    return ret;
}

static ssize_t mctp_read(struct file *filp, char __user *buf, size_t len, loff_t *data)
{
    char *key = NULL;
    size_t value = -1;
    int ret = -EAGAIN;

    if (str_node_count > 0)
    {
        key = dequeue(&global_queue);
        if (!key)
        {
            str_node_count--;
            return -EAGAIN;
        }
        str_node_count--;
    } else {
        return -EAGAIN;
    }

    char hex_byte[3] = {0};
    unsigned int msg_type = 0;

    strncpy(hex_byte, key, 2);
    if (kstrtouint(hex_byte, 16, &msg_type) != 0)
    {
        pr_err("MCTP invalid msg_type format: %s", hex_byte);
        return -EINVAL;
    }

    switch (msg_type)
    {
        case 0x00:
            value = lookup_fixed_table(key, 14);
            pr_debug("mctp Key: %s, Value: 0x%08x, msg_type: 0x%08x", key, value, msg_type);
            if (value != 0xF)
            {
                ret = read_control_bin(value, buf, key);
                return ret < 0 ? ret : len;
            }
            break;
        case 0x02:
            value = lookup_fixed_table(key, 18);
            pr_debug("mctp Key: %s, Value: 0x%08x, msg_type: 0x%08x", key, value, msg_type);
            if (value != 0xF)
            {
                ret = read_ncsi_bin(value, buf, key);
                return ret < 0 ? ret : len;
            }
            break;
        default:
            break;
    }

    return -EAGAIN;
}

static const char* get_mctp_control_context(const MCTP_BaseHeader* base, const MCTP_ControlExtHeader* ext, char* ctx_str, size_t len)
{
    snprintf(ctx_str, len,
        "%02x%04x%04x%02x%02x%02x%02x%02x",
        base->msg_type & 0x7F,
        le16_to_cpu(base->requester_id),
        le16_to_cpu(base->target_id),
        base->source_eid,
        ext->command_code,
        base->msg_tag & 0x07,
        base->dest_eid,
        ext->instance_id);
    
    return ctx_str;
}

static const char* get_ncsi_context(const MCTP_BaseHeader* base, const MCTP_NCSIExtHeader* ext, const char* buffer, size_t len, char * ctx_str, size_t ctx_len)
{
    uint8_t hw_cmd = 0, sub_cmd = 0, extra_cmd = 0;
    if (ext->command_type == 0x50 && len >= 38 + sizeof(Huawei_CmdExtension))
    {
        const Huawei_CmdExtension* hw_ext = (const Huawei_CmdExtension*)(buffer + 38);
        hw_cmd = hw_ext->huawei_cmd_id;
        sub_cmd = hw_ext->sub_cmd_id;
        if (sub_cmd == 0x0E && hw_cmd == 0x00)
        {
            extra_cmd = hw_ext->extra_cmd;
        }
    }


    snprintf(ctx_str, ctx_len,
        "%02x%04x%02x%02x%02x%02x%02x%02x%04x%02x%02x%02x%02x",
        base->msg_type & 0x7F,
        le16_to_cpu(base->requester_id),
        base->source_eid,
        ext->mc_id,
        ext->command_type,
        hw_cmd,
        sub_cmd,
        extra_cmd,
        le16_to_cpu(base->target_id),
        base->dest_eid,
        ext->channel_id,
        ext->iid,
        base->msg_tag & 0x07);
    
    return ctx_str;
}

const char* get_buffer_context_enhanced(const char* buffer, size_t len)
{
    /* 基础头校验 */
    if (len < sizeof(MCTP_BaseHeader))
    {
        pr_err("Invalid header length:%zu < %zu \n", len, sizeof(MCTP_BaseHeader));
        return NULL;
    }

    const MCTP_BaseHeader* base = (const MCTP_BaseHeader*)buffer;
    static char ctx_str[128];

    /* 计算MCTP有效长度 */
    const uint16_t mctp_len = (base->mctp_hdr.length_high << 8) | base->mctp_hdr.length_low;
    if (mctp_len > 0x3FF)
    {
        pr_err("Invalid MCTP length: 0x%04x\n", mctp_len);
        return NULL;
    }

    /* 根据消息类型分发处理 */
    const uint8_t msg_type = base->msg_type & 0x7F;
    switch (msg_type)
    {
        case 0x00:
            if (len < sizeof(MCTP_BaseHeader) + sizeof(MCTP_ControlExtHeader))
            {
                pr_err("Control message too short.\n");
                return NULL;
            } else
            {
                const MCTP_ControlExtHeader* ext = (const MCTP_ControlExtHeader*)(buffer + sizeof(MCTP_BaseHeader));
                return get_mctp_control_context(base, ext, ctx_str, sizeof(ctx_str));
            }
            break;
        case 0x02:
            if (len < sizeof(MCTP_BaseHeader) + sizeof(MCTP_NCSIExtHeader))
            {
                pr_err("NCSI message too short.\n");
                return NULL;
            } else{
                const MCTP_NCSIExtHeader* ext = (const MCTP_NCSIExtHeader*)(buffer + sizeof(MCTP_BaseHeader));
                return get_ncsi_context(base, ext, buffer, len, ctx_str, sizeof(ctx_str));
            }
            break;
        default:
            pr_err("Unsupported message type: 0x%02x.\n", msg_type);
            return NULL;
    }
    return ctx_str;
}

static int safe_enqueue(const char *data)
{
    int ret = 0;
    unsigned long flags;
    ret = enqueue(&global_queue, data);;

    return ret;
}

/* 命令处理函数 */
static int process_commands(u32 match_key)
{
    const struct cmd_entry* entry = NULL;

    size_t i;

    /* 查找匹配项 */
    for (i = 0; i < ARRAY_SIZE(command_table); ++i)
    {
        if (command_table[i].match_key == match_key)
        {
            entry = &command_table[i];
            break;
        }
    }

    if (!entry)
    {
        return 0;
    }

    for (i = 0; i < entry->item_count; ++i)
    {
        if (safe_enqueue(entry->data_items[i]) != 0)
        {
            pr_err("Enqueue failed for item: %zu\n", i);
            return -EFAULT;
        }

        str_node_count ++;
        write_count ++;
    }

    return 0;
}


static ssize_t mctp_write(struct file *filp, const char __user *buf, size_t length, loff_t *data)
{
    int ret;

    if (bdf_change() > 0)
    {
        ret = change_routing_table();

        if (enqueue(&global_queue, "00000000000000") == 0)
        {
            str_node_count++;
        } else {
            pr_err("mctp enqueue failed\n");
        }
    }

    unsigned char *write_buffer = kmalloc(MCTP_MAX_PACKET_SIZE, GFP_KERNEL);
    if (!write_buffer)
    {
        pr_err("mctp kmalloc write_buffer failed.\n");
        return -ENOMEM;
    }
    
    if (copy_from_user(write_buffer, buf, length))
    {
        kfree(write_buffer);
        pr_err("copy from user failed.\n");
        return -EFAULT;
    }

    const char* ctx = get_buffer_context_enhanced((const char*)write_buffer, length);

    if (ctx) {
        if (enqueue(&global_queue, ctx) == 0)
        {
            str_node_count++;
            write_count++;
        } else {
            pr_err("mctp write enqueue failed.\n");
            kfree(write_buffer);
            return -1;
        }
    } else {
        pr_err("Invalid mctp write packet.\n");
        kfree(write_buffer);
        return -1;
    }

    kfree(write_buffer);

    size_t ctx_len = (ctx != NULL) ? strlen(ctx) : 0;

    u32 match_key = form_match_key(ctx);

    ret = process_commands(match_key);

    if (ret < 0)
    {
        return ret;
    }
    return (ssize_t)length;
}

int deal_cmd_config_table(unsigned long arg)
{
    return 0;
}

int deal_cmd_config_eid_table(unsigned long arg)
{
    return 0;
}

int deal_cmd_statistics(unsigned long arg)
{
    return 0;
}

int mctp_read_config_info(unsigned long arg)
{
    return 0;
}

static void init_mctp_hardware(void)
{
    if (enqueue(&global_queue, "00000000000000") == 0)
    {
        str_node_count ++;
    } else {
        pr_err("mctp init hardware enqueue failed.\n");
    }
}

static int mctp_reinit_hardware(void)
{
    init_mctp_hardware();
    return 0;
}

static long mctp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    int retval;

    retval = comm_ioc_parm_check(cmd, (void __user *)arg, MCTP_IOC_MAGIC, MCTP_IOC_MAXNR);
    if (retval)
    {
        return retval;
    }

    switch (cmd)
    {
        case MCTP_CMD_CONFIG_TABLE:
            retval = deal_cmd_config_table(arg);
            if (retval)
            {
                return retval;
            }
            break;
        
        case MCTP_CMD_CONFIG_EID_TABLE:
            retval = deal_cmd_config_eid_table(arg);
            if (retval)
            {
                return retval;
            }
            break;

        case MCTP_CMD_REINIT:
            retval = mctp_reinit_hardware();
            if (retval)
            {
                return retval;
            }
            break;
        
        case MCTP_CMD_STATISTICS:
            retval = deal_cmd_statistics(arg);
            if (retval)
            {
                return retval;
            }
            break;
        case MCTP_CMD_CONFIG_INFO:
            return mctp_read_config_info(arg);
        
        default:
            retval = -EINVAL;
            break;
    }

    return retval;
}

static const struct file_operations fops = {
    .owner = THIS_MODULE,
    .read = mctp_read,
    .write = mctp_write,
    .unlocked_ioctl = mctp_ioctl,
};

static int mctp_init(void) {
    int ret;

    // 动态分配设备号
    ret = alloc_chrdev_region(&devt, 0, 1, DEVICE_NAME);
    if (ret < 0) {
        pr_err("Failed to allocate device number\n");
        return ret;
    }

    // 初始化并添加字符设备
    cdev_init(&mctp_cdev, &fops);
    ret = cdev_add(&mctp_cdev, devt, 1);
    if (ret < 0) {
        pr_err("Failed to add cdev\n");
        goto err_cdev;
    }

    // 创建设备类
    mctp = class_create(THIS_MODULE, CLASS_NAME);
    if (IS_ERR(mctp)) {
        ret = PTR_ERR(mctp);
        pr_err("Failed to create class\n");
        goto err_class;
    }

    // 创建设备节点
    if (IS_ERR(device_create(mctp, NULL, devt, NULL, DEVICE_NAME))) {
        pr_err("Failed to create device\n");
        ret = -1;
        goto err_device;
    }

    pr_debug("Driver loaded\n");

    init_mctp_hardware();
    return 0;

err_device:
    class_destroy(mctp);
err_class:
    cdev_del(&mctp_cdev);
err_cdev:
    unregister_chrdev_region(devt, 1);
    return ret;
}

static void mctp_exit(void) {
    device_destroy(mctp, devt);
    class_destroy(mctp);
    cdev_del(&mctp_cdev);
    unregister_chrdev_region(devt, 1);
    pr_debug("Driver unloaded\n");
}

static int __init mctp_module_init(void)
{
    init_queue(&global_queue);
    int ret = calculate_init_md5();

    /* 创建单线程工作队列 */
    cache_cleanup_wq = create_singlethread_workqueue("cache_cleanup");
    if (!cache_cleanup_wq) {
        pr_err("Failed to create workqueue\n");
        return -ENOMEM;
    }

    /* 初始化延迟工作 */
    INIT_DELAYED_WORK(&cache_cleanup_work, cache_cleanup_work_fn);

    /* 提交第一个工作项 */
    queue_delayed_work(cache_cleanup_wq, &cache_cleanup_work, 0);

    /* 初始化延迟工作 */
    
    return mctp_init();
}

static void __exit mctp_module_exit(void)
{
    cleanup_all_file_cache();
    destroy_queue(&global_queue);
    cancel_delayed_work_sync(&cache_cleanup_work);
    destroy_workqueue(cache_cleanup_wq);
    mctp_exit();
}

module_init(mctp_module_init);
module_exit(mctp_module_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("openUBMC-qemu");
